package guiTicTacToe;

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

import botTicTacToe.*;

public class TicTacToeGUI extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static final String TITLE = "Tic Tac Toe";
	private static final int WIDTH = 450;
	private static final int HEIGHT = 600;

	private Container content;
	private JLabel result;
	private JButton[] cells;
	private JButton exitButton;
	private JButton initButton;
	private CellButtonHandler[] cellHandlers;
	private ExitButtonHandler exitHandler;
	private InitButtonHandler initHandler;

	private GameField field;
	private GameBot botX;
	private GameBot botO;
	
	private enum gameModes {
		HvC,
		CvH,
		HvH,
		CvC
	}
	
	gameModes gameMode;
	
	boolean noughts;

	public TicTacToeGUI() {
		// Necessary initialization code
		setTitle(TITLE);
		setSize(WIDTH, HEIGHT);
		setDefaultCloseOperation(EXIT_ON_CLOSE);

		// Get content pane
		content = getContentPane();
		content.setBackground(Color.blue.darker());

		// Set layout
		content.setLayout(new GridLayout(4, 3));

		// Create cells and handlers
		cells = new JButton[9];
		cellHandlers = new CellButtonHandler[9];
		for (int i = 0; i < 9; i++) {
			char ch = (char) ('0' + i + 1);
			cells[i] = new JButton("" + ch);
			cellHandlers[i] = new CellButtonHandler();
			cells[i].addActionListener(cellHandlers[i]);
		}

		// Create init and exit buttons and handlers
		exitButton = new JButton("EXIT");
		exitHandler = new ExitButtonHandler();
		exitButton.addActionListener(exitHandler);
		initButton = new JButton("CLEAR");
		initHandler = new InitButtonHandler();
		initButton.addActionListener(initHandler);

		// Create result label
		result = new JLabel("Noughts", SwingConstants.CENTER);
		result.setForeground(Color.white);

		// Add elements to the grid content pane
		for (int i = 0; i < 9; i++) {
			content.add(cells[i]);
		}
		content.add(initButton);
		content.add(result);
		content.add(exitButton);

		// Initialize
		init();
	}
	
	private void turn(int cellN) {
		if (field.placeMark(noughts? GameField.MARK_O : GameField.MARK_X, cellN)) {
			cells[cellN].setText(noughts? "O" : "X");
			
			if (botX != null)
				if (botX.inited()) botX.turn(cellN);
				else botX.init(field, noughts? GameField.MARK_X : GameField.MARK_O);
			if (botO != null)
				if (botO.inited()) botO.turn(cellN);
				else botO.init(field, noughts? GameField.MARK_X : GameField.MARK_O);
			
			// Check winner
			if (field.isGameEnd()) {
				// Display winner message
				if (field.getWinner() != GameField.WINNER_DRAW)
					result.setText((noughts? "Noughts" : "Crosses") + " win!");
				else result.setText("Draw!");
			} else {
				// Change player
				noughts = !noughts;
	
				// Display player message
				result.setText(noughts? "Noughts" : "Crosses");
				
				// Process bots
				if (botO != null) {
					if (noughts) {
						int botTurn = botO.getTurn();
						turn(botTurn);
					}
				}
				if (botX != null) {
					if (!noughts) {
						int botTurn = botX.getTurn();
						turn(botTurn);
					}
				}
			}
		}		
	}

	public void init() {
		// Initialize text in buttons
		for (int i = 0; i < 9; i++) {
			cells[i].setText("");
		}

		// Initialize result label
		result.setText("Noughts");
		
		noughts = true;
		
		botX = null;
		botO = null;
		
		field = new GameField();

		setVisible(true);
		
		String[] modes = {"Human - Computer",
				"Computer - Human",
				"Human - Human",
				"Computer - Computer"};
		
		String mode = (String) JOptionPane.showInputDialog(
				null,
				"Choose game mode",
				"Mode selection",
				JOptionPane.INFORMATION_MESSAGE,
				null, modes, modes[0]);
		
		if (mode == null) System.exit(0);
		
		for (int i = 0; i < modes.length; i++)
			if (modes[i] == mode) {
				gameMode = gameModes.values()[i];
				break;
			}
		
		switch (gameMode) {
		case HvC:
			botX = new GameBot(GameField.MARK_X);
			break;
			
		case CvH:
			botO = new GameBot(GameField.MARK_O);
			botO.init(noughts? GameField.MARK_O : GameField.MARK_X);
			turn(botO.getTurn());
			break;
			
		case CvC:
			botX = new GameBot(GameField.MARK_X);
			botO = new GameBot(GameField.MARK_O);
			botO.init(noughts? GameField.MARK_O : GameField.MARK_X);
			turn(botO.getTurn());
			break;
			
		default:
		}
	}

	public static void main(String[] args) {
		// Create TicTacToe object
		// TicTacToeGUI gui =
		new TicTacToeGUI();

	}
	

	private class CellButtonHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			if (gameMode == gameModes.CvC) return;
			
			// Get button pressed
			JButton pressed = (JButton) (e.getSource());

			for (int i = 0; i < cells.length; i++) {
				if (pressed == cells[i]) {
					turn(i);
					break;
				}
			}
		}
	}

	private class ExitButtonHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			System.exit(0);
		}
	}

	private class InitButtonHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			init();
		}
	}
}
